home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / VideoToolbox 96.06.15 / (Utilities) / CVNetConvert / cvnetcnv.c < prev    next >
Text File  |  1995-08-13  |  28KB  |  837 lines

  1. /* cvnetcnv.c - CVNet master member list format converter.
  2.    This program converts CVNet master member list into other data formats
  3.     suitable for importing into a variety of database programs.
  4.     By defining the desired output format in file "cvnetcnv.fmt"
  5.     in the current directory, the program can be customized for
  6.     nearly all kinds of format conversion needs.  Format specification
  7.     files for some common data formats are included in the package.
  8.  
  9.    The program has been tested on the following machines and operating systems.
  10.     BSD Unix 4.3
  11.     Sun 4 (SunOS Release 4.1)
  12.     NeXT (NeXT OS Release 2.1)
  13.     IBM PC/Clones (MSDOS 5.0)
  14.         Microsoft C (v5.1), Turbo C (v2.0), Turbo C++ (v1.0)
  15.     Macintosh (System 7)
  16.         THINK C
  17.  
  18.    This program is not copyrighted.  You are free to do whatever
  19.     you want with it.
  20.  
  21.    Send comments, bug fixes, support for other machines/OS, and additonal
  22.     format specification files to: izumi@pinoko.berkeley.edu.
  23.  
  24.    Up-to-date version of this program and additional format specification files
  25.     will be available via anonymous FTP from our machine
  26.     "pinoko.berkeley.edu" in directory: /pub/CVNet.
  27.  
  28.    This program is in no way guaranteed to do anything useful for you.
  29.    More likely, it will distract your attention from your research.
  30.  
  31.    ---------------------------------------------------------------------------
  32.    Usage (Unix, PC):
  33.     cvnetcnv inputfile outputfile [formatfile]
  34.  
  35.    "Inputfile" is a file containing the CVNet master member list as obtained
  36.    from Listserv@vm1.yorkU.ca by sending it a one-line message that says:
  37.    GET MEMBER FILE
  38.    You do not have to edit out the e-mail header and little notes at the
  39.    beginning and end of the e-mail text.
  40.  
  41.    "Outputfile" will contain the result of conversion performed per
  42.    specification in file "cvnetcnv.fmt".
  43.  
  44.    "Formatfile" may be given as an option when you want to override the
  45.    default use of "cvnetcnv.fmt".
  46.  
  47.     The Macintosh version (i.e. if MAC is defined) presents standard file
  48.     dialogs, asking you to open your CVNet master file, and how you want to
  49.     save it. You are asked to open your own format file only if it can't find
  50.     "cvnetcnv.fmt".
  51.    ---------------------------------------------------------------------------
  52.    To Compile:
  53.    NOTE -- Please check if the appropriate macro is defined for
  54.     UNIX, MSDOS, MAC or whatever.  These macros should be mutually
  55.     exclusive.  If you define MAC, comment out the others.
  56.  
  57.    UNIX
  58.     cc -o cvnetcnv cvnetcnv.c
  59.  
  60.    MSDOS (Uncomment #define MSDOS below. Same for Turbo C++)
  61.     cl cvnetcnv.c (MSC)
  62.     tcc cvnetcnv.c (Turbo C)
  63.  
  64.    Macintosh THINK C
  65.         Uncomment #define MAC below. Use the supplied project file cvnetcnv.π. It
  66.         will create an application called CVNetConvert, which is a stand-alone
  67.         Macintosh application, suitable for double clicking. CVNetConvert
  68.         should work fine on all Macs and Systems 6 and 7, but was only tested on 
  69.         Mac IIci with System 7. The only portability problem I can conceive of is
  70.         the need for ALRT resource -16405, which is present in Systems 6.07 and 7.
  71.    ---------------------------------------------------------------------------
  72.    To Prepare Conversion Format Specification File:
  73.  
  74.    The first line of the format file specifies the record format. You may use 
  75.    the following variable names. All other characters not listed below will 
  76.    be written out to the output as is.
  77.  
  78.         $L -- last name
  79.         $F -- first name & initial
  80.         $I -- institutional affiliation
  81.         $A -- address (e-mail)
  82.         $T -- TAB character
  83.         $N -- NEW LINE character (LF for UNIX, CRLF for MSDOS)
  84.         $Cnn -- advance to column nn if possible (if not past it already)
  85.  
  86.     For example, this format line
  87.         $L$C12$F$C22($I)$C43<$A>,
  88.     produces a file suitable for UNIX "mail/sendmail":
  89.         Abramov    Israel    (Brooklyn College)   <ixrbc@cunyvm.bitnet>,
  90.  
  91.     [#### Warning.  Don't send E-mails to everyone on CVNet using the alias file
  92.      you can obtain this way.  That is ABUSE of the database.]
  93.  
  94.     On the second line, a line beginning with $M may appear optionally. If present,
  95.     it specifies the output file's Macintosh file type and creator (ignored unless 
  96.     the program is running on a Mac).  If not present, the file type/creator
  97.     will be set to that of MacWrite text file.
  98.     
  99.     After the $M line, or on the second line if $M line does not appear,
  100.     a line beginning with $P may appear optionally (which may continue for
  101.     multiple lines).  If present, it will specify the prolog, text placed
  102.     at the beginning of the output file before all address records.
  103.     After this, a line beginning with $E may appear optionally (which
  104.     may continue for multiple lines).  If present, it will specify the
  105.     epilog, text placed at the end of the output file after all
  106.     address records.  
  107.     
  108.     $M, $P, $E must appear in that order if all three are present.
  109.     Not all of them have to be present, e.g., if no prolog is needed
  110.     but epilog is required, $M, $E lines should be entered in that order.
  111.     
  112.     There must not be any blank or extraneous lines between the first line
  113.     and $M.  Similarly, no blank or extraneous lines should be present
  114.     between $M, $P, $E specifications.  However, blank lines are allowed
  115.     within the quoted text for the prolog and epilog. 
  116.     
  117.     $M, $P, $E must appear at column 1 without any leading spaces.
  118.  
  119.     
  120.     $Mttttcccc -- specify the output file's four-character Macintosh type 
  121.         (e.g. TEXT) and creator (e.g. MACA). The rest of the line is ignored.
  122.     $P^prolog text^ -- Place the text between quote chars at the beginning of
  123.         the output file.
  124.     $E^epilog text^ -- Place the text between quote chars at the end of the
  125.         output file.
  126.     
  127.     The prolog and epilog may extend over many lines. The character that 
  128.     immediately follows $P and $E is used as the "quote" character to 
  129.     mark the range of text for prolog and epilog.  The quote char may be any 
  130.     printable character that is not used in the quoted text for the 
  131.     prolog and epilog. The rest of the line after the terminating quote is 
  132.     ignored. After the optional $M, $P, and $E the rest of the file is ignored.
  133.     
  134.     The QuickDEX.fmt format file produces a Macintosh file
  135.     suitable for use with the Rolodex-like program called QuickDEX:
  136.         *$NN$F $L$N$I$N$A
  137.         $MTEXTQDEx
  138.         $P^
  139.         *
  140.         ^
  141.         $E^*
  142.         *
  143.         ^
  144.     The first line specifies the record format, which produces records like this:
  145.         *
  146.         NIsrael Abramov
  147.         Brooklyn College
  148.         ixrbc@cunyvm.bitnet
  149.     The line beginning with $M specifies the Macintosh file type (TEXT) and creator
  150.     (QDEx) so that QuickDEX will recognize it. The lines beginning with $P and $E 
  151.     specify a prolog and epilog, adding some extra *'s and linefeeds to please QuickDEX.
  152.  
  153.     Here are some more examples:
  154.     
  155.     Revert to the old format of CVNet master list (but without continuation lines):
  156.         $L$C12$F$C22$I$C43$A
  157.     produces
  158.         Abramov    Israel    Brooklyn College     ixrbc@cunyvm.bitnet
  159.  
  160.     Tab-separated ASCII format for importing into NeXT SpeedDeX application:
  161.         $L, $F$T$A$T$I
  162.     produces
  163.         Abramov, Israel    ixrbc@cunyvm.bitnet    Brooklyn College
  164.                        ^                   ^
  165.                       TAB                 TAB
  166.  
  167.     A basic format might demarcate field by quotes and commas:
  168.         "$L", "$F", "$I", "$A"
  169.     produces
  170.         "Abramov", "Israel", "Brooklyn College", "ixrbc@cunyvm.bitnet"
  171.  
  172.    ---------------------------------------------------------------------------
  173.    Revision history:
  174.    V1.00, 92-06-07, Izumi Ohzawa, izumi@pinoko.berkeley.edu
  175.    V1.01, 92-06-15, Denis_Pelli@isr.syr.edu added support for Macintosh.
  176.    V1.02, 92-06-16, Izumi Ohzawa, added support for Prolog, Epilog.
  177.    V1.03, 92-06-16, Denis Pelli, set type and creator of Mac files
  178.    V1.04, 92-06-17, Izumi & Denis, minor fixups for portability
  179.    V1.05, 92-07-01, Denis fixed bug reported by Larry Thibos, can now open
  180.                        files in any folder.
  181.    v1.06?,4/25/93, Denis changed call to Macintosh SFGetFile() to only list TEXT files.
  182.                        Enhanced fatal error message.
  183.    v1.07?,6/12/94, Denis updated for compatibility with Apple's Universal header files.
  184.                        #define __STDC__ if MAC is true.
  185.                        #define c2pstr and p2cstr in terms of Symantec's CtoPstr and PtoCstr.
  186.    ---------------------------------------------------------------------------
  187. */
  188.  
  189. /* ####### Uncomment the one that is appropriate for your environment ########### */
  190. /* #define UNIX      1 */        /* Sun, NeXT, BSD, and others */
  191. /* #define MSDOS     1 */        /* Microsoft C, Turbo C, C++ for MSDOS */
  192. #define MAC       1             /* Macintosh THINK C */
  193. #ifdef MAC
  194.     #pragma only_std_keywords off
  195. #endif
  196. #include <stdio.h>
  197. #ifdef UNIX
  198. #include <strings.h>
  199. #endif
  200. #ifdef MSDOS
  201. #include <string.h>
  202. #endif
  203. #ifdef MAC
  204.     /*
  205.         Mac C compilers include extensions beyond Standard C, but
  206.         for the purposes of this file are best thought of as Standard C.
  207.     */
  208.     #ifndef __STDC__
  209.         #define __STDC__ 0
  210.     #endif
  211.     #include <string.h>
  212.     #include <StandardFile.h>
  213.     #include <QuickDraw.h>
  214.     #include <Memory.h>
  215.     #include <Fonts.h>
  216.     #include <Dialogs.h>
  217.     #include <Events.h>
  218.     #include <OSEvents.h>
  219.     #include <Files.h>
  220.     #if THINK_C
  221.         #include <pascal.h>    /* CtoPStr() and PtoCStr() */
  222.         #ifndef c2pstr
  223.             #define c2pstr CtoPstr
  224.             #define p2cstr PtoCstr
  225.         #endif
  226.     #else
  227.         #include <Strings.h>/* c2pstr() and p2cstr() */
  228.     #endif
  229.     EventRecord event;
  230.     static void SetFileInfo(char *fileName,OSType fileType,OSType fileCreator);
  231. #endif
  232.  
  233. #ifdef __STDC__            /* ANSI-C-style prototypes */
  234. #include <stdlib.h>        /* exit() and atoi() */
  235. void usage(void);
  236. void stupid(void);
  237. char *findex(char *str, char ch);
  238. void remove_comma(char *str);
  239. int check_address(char *str);
  240. void outstring(char *str, FILE *fp);
  241. void outchar(int c, FILE *fp);
  242. void write_record(FILE *fp);
  243. #endif
  244.  
  245. /* Bad Bad Globals */
  246. int linecnt = 0;        /* number of lines including junk for error report */
  247. int recordcnt = 0;        /* number of records processed */
  248. int column = 1;            /* current column position of output */
  249. char *okchar = "!@%.+-_/";    /* non-alphanumerics that are OK in e-mail address */
  250. char *deffile = "cvnetcnv.fmt";    /* default filename for target format specification */
  251. char *fmtfile;            /* either deffile or argv[3] if given */
  252. char fmt[256];            /* output format string read from fmtfile */
  253. char linebuf[256];        /* line buffer for CVNet file */
  254. char fLineBuffer[256];        /* line buffer for format file */
  255. char tmpbuf[256];        /* buffer for processing */
  256. char lastname[128];        /* Storage for last name */
  257. char firstini[128];        /* Storage for first name, initial */
  258. char affiliation[128];        /* Storage for institutional affiliation */
  259. char emaddress[128];        /* Storage for e-mail address */
  260.  
  261. #ifdef MAC
  262. static void SetFileInfo(char *fileName,OSType fileType,OSType fileCreator)
  263. {
  264.     FInfo outFileInfo;
  265.     
  266.     c2pstr(fileName);
  267.     GetFInfo((StringPtr)fileName,0,&outFileInfo);
  268.     outFileInfo.fdType = fileType;
  269.     outFileInfo.fdCreator = fileCreator;
  270.     SetFInfo((StringPtr)fileName,0,&outFileInfo);
  271.     p2cstr((void *)fileName);
  272. }
  273. #endif
  274.  
  275. /* __STDC__ is a predefined macro for ANSI-standard C.
  276.  * This stuff is needed to increase portability for some obsolete C compilers.
  277.  */
  278.  
  279. #ifdef __STDC__
  280. void usage(void)
  281. #else
  282. usage()
  283. #endif
  284. {
  285. #ifdef MAC
  286.         printf("This program asks you to open your CVNet master file,\n");
  287.         printf("     and how you want to save it.\n");
  288.         printf("     And, unless there is a format file called \"%s\",\n",deffile);
  289.         printf("     asks you to open your own format file.\n");
  290.         fmtfile=deffile;
  291. #else
  292.     printf("Usage: cvnetcnv inputfile outputfile [formatfile]\n");
  293. #endif
  294.     printf("  *This program converts the CVNet master list to another format\n");
  295.     printf("     as specified in file <%s>.\n", fmtfile);
  296.     printf("     Please look at example format specification files with *.fmt\n");
  297.     printf("     extension.\n");
  298.     printf("  *You do not have to edit out the E-mail header or any other\n");
  299.     printf("     text at the beginning and end of input file.\n");
  300. #ifdef MAC
  301.         printf("Click this window to exit:\n");
  302.         FlushEvents(everyEvent,0);
  303.         while(!GetNextEvent(everyEvent,&event)) ;
  304. #endif
  305.     exit(1);
  306. }
  307.  
  308. #ifdef __STDC__
  309. void stupid(void)
  310. #else
  311. stupid()
  312. #endif
  313. {
  314. printf("##### WARNING !!! WARNING !!! WARNING !!! WARNING !!! #####\n\n");
  315. printf("  Please DO NOT ABUSE the computer readable database you\n");
  316. printf("generate using this program.  Mailing directly from your\n");
  317. printf("computer to all members of CVNet is *ABUSE*!  No matter\n");
  318. printf("how hot a manuscript or how great a product you have, do\n");
  319. printf("not send mails to everyone directly.  If you think you have\n");
  320. printf("some important information for a lot of people, send it\n");
  321. printf("to CVNET@vm1.yorku.ca.  It will not be sent to the members\n");
  322. printf("automatically, however.  The coordinator of CVNet will\n");
  323. printf("review your submission according to the rules developed\n");
  324. printf("over the years as a result of feedback from the members.\n");
  325. printf("  Please also do not give out the database to non-members.\n");
  326. printf("  I wrote this program to give us convenience in finding\n");
  327. printf("the e-mail address of our colleagues.  Abuse of the\n");
  328. printf("database will lead to your expulsion from CVNet,\n");
  329. printf("not to mention that everyone will hate you for it.\n");
  330. printf("###########################################################\n\n");
  331. #ifndef __STDC__
  332. return(0);
  333. #endif
  334. }
  335.  
  336.  
  337. /* Sigh. Not all C libraries include index(char *str, char ch) function */
  338. #ifdef __STDC__
  339. char *findex(char *str, char ch)
  340. #else
  341. char *findex(str, ch)
  342. char *str;
  343. char ch;
  344. #endif
  345. {
  346. char *p, *end;
  347.     p = end = str;
  348.     while(*end != '\0') end++;        /* end points to string terminator */
  349.     while(*p != ch && *p != '\0') p++;  /* p points to char ch if present */
  350.     if(p != end) return (p);
  351.     else {
  352.         fprintf(stderr, "\nFATAL ERROR: Line %d of input file is missing \"%c\" character:\n",
  353.             linecnt, ch);
  354.         fprintf(stderr, "%s\n",str);    /* dgp */
  355.         fprintf(stderr,"\nBEWARE: the output file is incomplete.\n");
  356. #ifdef MAC
  357.         printf("Click this window to exit:\n");
  358.         FlushEvents(everyEvent,0);
  359.         while(!GetNextEvent(everyEvent,&event)) ;
  360. #endif
  361.         exit(4);
  362.     }
  363.     return (NULL);        /* it shouldn't come here */
  364. }
  365.  
  366.  
  367. #ifdef __STDC__
  368. void remove_comma(char *str)
  369. #else
  370. remove_comma(str)
  371. char *str;
  372. #endif
  373. {
  374. static char tmp[128];
  375. char *s, *t;
  376.     s = str;
  377.     t = tmp;
  378.     /* copy string to tmp[] while removing ',' */
  379.     while((*t = *s++) != '\0')
  380.         if(*t != ',') t++;
  381.     strncpy(str, tmp, 80);        /* copy back to original string */
  382. #ifndef __STDC__
  383. return(0);
  384. #endif
  385. }
  386.  
  387. /* Check for invalid characters in e-mail address */
  388. /* Non-zero if there is a character that is not supposed to be in address */
  389. #ifdef __STDC__
  390. int check_address(char *str)
  391. #else
  392. int check_address(str)
  393. char *str;
  394. #endif
  395. {
  396. char *p, c;
  397. int i, nc, ok, retcode = 0;
  398.     p = str;
  399.     nc = strlen(okchar);
  400.     while((c = *p++) != '\0') {
  401.         ok = 0;
  402.         if(c >= 'a' && c <= 'z') continue;
  403.         if(c >= 'A' && c <= 'Z') continue;
  404.         if(c >= '0' && c <= '9') continue;
  405.         for(i=0; i<nc; i++) {
  406.         if(c == okchar[i]) {
  407.             ok =1;
  408.             break;    /* out of for() loop */
  409.         }
  410.         }
  411.         if(ok) continue;    /* while loop */
  412.         else {
  413.         retcode = c;
  414.         break;        /* out of while loop */
  415.         }
  416.     }
  417.     return(retcode);
  418. }
  419.  
  420.  
  421. #ifdef __STDC__
  422. void outstring(char *str, FILE *fp)
  423. #else
  424. outstring(str, fp)
  425. char *str;
  426. FILE *fp;
  427. #endif
  428. {
  429. char *p;
  430. int c;
  431.     p = str;
  432.     while((c = *p++) != '\0') {
  433.         putc(c, fp);
  434.         column++;
  435.     }
  436. #ifndef __STDC__
  437. return(0);
  438. #endif
  439. }
  440.  
  441.  
  442. #ifdef __STDC__
  443. void outchar(int c, FILE *fp)
  444. #else
  445. outchar(c, fp)
  446. int c;
  447. FILE *fp;
  448. #endif
  449. {
  450.     putc(c, fp);
  451.     column++;    /* GLOBAL column counter */
  452. #ifndef __STDC__
  453. return(0);
  454. #endif
  455. }
  456.  
  457.  
  458. /* Writes out each E-mail address record to output file */
  459. #ifdef __STDC__
  460. void write_record(FILE *fp)
  461. #else
  462. write_record(fp)
  463. FILE *fp;
  464. int atoi();    // The MetroWerks CodeWarrior C compiler is Standard C and doesn't like this.
  465. #endif
  466. {
  467. int ch, cmd, cto, i, cend;
  468. char *p;
  469. char *n;
  470. static char cnn[16];
  471.     column = 1;    /* GLOBAL, current column position */
  472.     p = fmt;    /* pointer to format string */
  473.     while((ch = *p++) != '\0') {
  474.         switch(ch) {
  475.         /* Formatting code for variables. Case-sensitive
  476.              $L -- last name
  477.              $F -- first name & initial
  478.              $I -- institutional affilication
  479.              $A -- address (e-mail)
  480.              $T -- TAB character
  481.              $N -- NEW LINE character (LF for UNIX, CRLF for MSDOS)
  482.              $Cnn -- advance to column nn if possible (if not past it already)
  483.          */
  484.         case '$':     /* special formatting code */
  485.             if((cmd = *p) == '\0') break;
  486.             p++;        /* advance ptr only if not at '\0' already */
  487.             switch(cmd) {
  488.                 case 'L':    /* last name */
  489.                 outstring(lastname, fp); break;
  490.                 case 'F':    /* first name & initial */
  491.                 outstring(firstini, fp); break;
  492.                 case 'I':    /* institutional affiliation */
  493.                 outstring(affiliation, fp); break;
  494.                 case 'A':    /* email address */
  495.                 outstring(emaddress, fp); break;
  496.                 case 'T':    /* TAB character insert */
  497.                 outchar('\t', fp); break;
  498.                 case 'N':    /* NEW LINE character insert */
  499.                 outchar('\n', fp); break;
  500.                 case 'C':    /* column advance */
  501.                 n = cnn;    /* number buffer for target column pos */
  502.                 while((*n = *p) >='0' && *n <='9') {
  503.                     n++; p++;
  504.                 }
  505.                 *n = '\0';        /* string terminator */
  506.                 cto = atoi(cnn);    /* move to cto */
  507.                 if(cto < 1 ) cto = 1;
  508.                 if((cend = cto-column) > 0) {
  509.                     for(i=0; i<cend; i++)
  510.                     outchar(' ', fp);
  511.                 }
  512.                 else    outchar(' ', fp);
  513.                 break;
  514.                 default:  /* This shouldn't happen */
  515.                 fprintf(stderr, "\nIllegal variable \"$%c\" in \"%s\".\n",
  516.                         cmd, fmtfile);
  517. #ifdef MAC
  518.                     printf("Click this window to exit:\n");
  519.                     FlushEvents(everyEvent,0);
  520.                     while(!GetNextEvent(everyEvent,&event)) ;
  521. #endif
  522.                 exit(5);
  523.             } /* end switch(cmd) */
  524.             break;
  525.  
  526.         default: /* regular ascii */
  527.             outchar(ch, fp);
  528.             break;
  529.         } /* end switch(ch) */
  530.     } /* end while((ch = *p) ... */
  531.  
  532. /*
  533.     fprintf(fp, "%s %s (%s) <%s>\n",
  534.             lastname, firstini, affiliation, emaddress);
  535. */
  536. #ifndef __STDC__
  537. return(0);
  538. #endif
  539. }
  540.  
  541.  
  542. #ifdef __STDC__
  543. void main(int argc, char *argv[])
  544. #else
  545. main(argc, argv)
  546. int argc;
  547. char *argv[];
  548. #endif
  549. {
  550. FILE *fpi, *fpf, *fpo;
  551. char *bptr, *eptr;
  552. int c;
  553. int charcnt;
  554. int quote;    /* prolog, epilog quote char */
  555. #ifdef MAC
  556.     Point where={200,100};
  557.     SFReply    reply;
  558.     char string[256];
  559.     /* The convention of storing four characters in a long, and of specifying
  560.     them with single quotes is not part of standard C, but is a standard
  561.     Macintosh extension to C. */
  562.     OSType type='TEXT',creator='MACA';    /* default is MacWrite text file */
  563.     short outputVRefNum,vRefNum;
  564. #endif
  565.         
  566. #ifdef MAC
  567.         InitGraf(&qd.thePort);
  568.         InitFonts();
  569.         InitWindows();
  570.         InitCursor();
  571.         argc=3;
  572. #endif
  573.     if(argc != 3 && argc != 4) usage();
  574.     stupid();
  575.  
  576.     /* Input file -- Original CVNet member list file */
  577. #ifdef MAC
  578.         printf("Where is the CVNet master list?\n");
  579.         printf("Click this window to continue:\n");
  580.         FlushEvents(everyEvent,0);
  581.         while(!GetNextEvent(everyEvent,&event)) ;
  582.         SFGetFile(where,NULL,NULL,1,&type,NULL,&reply);
  583.         if(!reply.good)usage();
  584.         p2cstr(reply.fName);
  585.         argv[1]=malloc(1+strlen((char *)reply.fName));
  586.         strcpy(argv[1],(char *)reply.fName);
  587.         c2pstr((char *)reply.fName);
  588.         SetVol(NULL,reply.vRefNum);    /* look in that folder */
  589. #endif
  590.     if((fpi = fopen(argv[1], "r")) == NULL) {
  591.         fprintf(stderr, "Can't open file \"%s\".\n", argv[1]);
  592. #ifdef MAC
  593.         printf("Click this window to exit:\n");
  594.         FlushEvents(everyEvent,0);
  595.         while(!GetNextEvent(everyEvent,&event)) ;
  596. #endif
  597.         exit(2);
  598.     }
  599.  
  600.     /* Output file. Check that we are not wiping out a *.fmt file. */
  601. #ifdef MAC
  602.         sprintf(string,"%s.out",argv[1]);
  603.         SFPutFile(where,"\pSave new CVNet list as:",c2pstr(string),NULL,&reply);
  604.         if(!reply.good)usage();
  605.         p2cstr(reply.fName);
  606.         argv[2]=malloc(1+strlen((char *)reply.fName));
  607.         strcpy(argv[2],(char *)reply.fName);
  608.         c2pstr((char *)reply.fName);
  609.         SetVol(NULL,reply.vRefNum);    /* look in that folder */
  610.         outputVRefNum=reply.vRefNum;
  611. #endif
  612.     bptr = eptr = argv[2];
  613.     while(*eptr != '\0') eptr++;
  614.     while(*bptr != '.' && *bptr != '\0') bptr++;
  615.     if(bptr != eptr) {
  616.         if(strncmp(bptr, ".fmt", 4) == 0) {
  617.         fprintf(stderr, "You shouldn't be writing to \"%s\".\n", argv[2]);
  618. #ifdef MAC
  619.             printf("Click this window to exit:\n");
  620.             FlushEvents(everyEvent,0);
  621.             while(!GetNextEvent(everyEvent,&event)) ;
  622. #endif
  623.         exit(1);
  624.         }
  625.     }
  626.     if((fpo = fopen(argv[2], "w")) == NULL) {
  627.         fprintf(stderr, "Can't open output file \"%s\".\n", argv[2]);
  628. #ifdef MAC
  629.         printf("Click this window to exit:\n");
  630.         FlushEvents(everyEvent,0);
  631.         while(!GetNextEvent(everyEvent,&event)) ;
  632. #endif
  633.         exit(3);
  634.     }
  635.  
  636.     /* Format file.
  637.      * Read the first few lines.
  638.      * The rest of the file will be ignored and may be used to describe
  639.      * the format specified in the file.
  640.      */
  641.     if(argc == 4) fmtfile = argv[3];    /* optional third argument given for fmt */
  642.     else          fmtfile = deffile;    /* default */
  643.     fpf = fopen(fmtfile, "r");
  644. #ifdef MAC
  645.         if(fpf==NULL){
  646.         sprintf(string,"Couldn't find \"%s\". Please choose a format file.",fmtfile);
  647.         ParamText(c2pstr(string),NULL,NULL,NULL);
  648.         Alert(-16405,NULL);
  649.         SFGetFile(where,NULL,NULL,1,&type,NULL,&reply);
  650.         if(!reply.good)usage();
  651.         p2cstr(reply.fName);
  652.         fmtfile=malloc(1+strlen((char *)reply.fName));
  653.         strcpy(fmtfile,(char *)reply.fName);
  654.         c2pstr((char *)reply.fName);
  655.         SetVol(NULL,reply.vRefNum);    /* look in that folder */
  656.         fpf = fopen(fmtfile, "r");
  657.         }
  658. #endif
  659.     if(fpf != NULL) {
  660.  
  661.         /* Read record-format string */
  662.         if((fgets(fmt, 250, fpf)) == NULL) {
  663.         fprintf(stderr, "Error reading format specification file \"%s\".\n", fmtfile);
  664. #ifdef MAC
  665.             printf("Click this window to exit:\n");
  666.             FlushEvents(everyEvent,0);
  667.             while(!GetNextEvent(everyEvent,&event)) ;
  668. #endif
  669.         exit(1);
  670.         }
  671.         fLineBuffer[0]=0;
  672.         fgets(fLineBuffer, 250, fpf);        /* read next line */
  673.         
  674.         /* Read optional file type specification */
  675.         if(strncmp(fLineBuffer, "$M", 2) == 0) {
  676. #ifdef MAC
  677.             strncpy((char *)&type,&fLineBuffer[2],4);
  678.             strncpy((char *)&creator,&fLineBuffer[6],4);
  679. #endif
  680.             fLineBuffer[0]=0;
  681.             fgets(fLineBuffer, 250, fpf);    /* read next line */
  682.         }
  683. #ifdef MAC
  684.         /* Set the output file's Macintosh type and creator. */
  685.         GetVol(NULL,&vRefNum);
  686.         SetVol(NULL,outputVRefNum);    /* look in that folder */
  687.         SetFileInfo(argv[2],type,creator);
  688.         SetVol(NULL,vRefNum);
  689. #endif
  690.  
  691.         /* Read optional prolog into output file */
  692.         if(strncmp(fLineBuffer, "$P", 2) == 0) {
  693.         quote = fLineBuffer[2];        /* set quote char for prolog */
  694.         bptr = &fLineBuffer[3];
  695.         while(1){
  696.                 while(((c = *bptr++) != quote) && c != '\0')
  697.                 putc(c, fpo);
  698.                 if(c == quote) break;
  699.                 if(fgets(fLineBuffer, 250, fpf) == NULL) break;
  700.                 bptr = fLineBuffer;
  701.         }
  702.         fLineBuffer[0]=0;
  703.         fgets(fLineBuffer, 250, fpf);    /* read next line */
  704.         }
  705.         /* Prolog done, but keep FILE *fpf open for epilog at the end */
  706.     } else {
  707.         fprintf(stderr, "Can't open conversion format specification file \"%s\".\n",
  708.                 fmtfile);
  709. #ifdef MAC
  710.         printf("Click this window to exit:\n");
  711.         FlushEvents(everyEvent,0);
  712.         while(!GetNextEvent(everyEvent,&event)) ;
  713. #endif
  714.         exit(1);
  715.     }
  716.  
  717.  
  718.     /* The program relies on the presence of "------" to indicate the
  719.      * start of records.  This could be a bad thing to rely on.
  720.      */
  721.     while( ( fgets(linebuf, 250, fpi) ) != NULL ) {
  722.         linecnt++;
  723.         if(strncmp(linebuf, "-----", 5) == 0)
  724.         break;        /* start of records detected */
  725.     }
  726.  
  727.     /* ---- Read a line and separate components into proper places ------ */
  728.     while((fgets(linebuf, 250, fpi)) != NULL) {
  729.         linecnt++;
  730.         charcnt = strlen(linebuf);
  731.         if(linebuf[0] == '#' || linebuf[0] == ';' || charcnt == 0)
  732.         continue;    /* blank or comment lines */
  733.         if(strncmp(linebuf, "-----", 5) == 0)
  734.         break;        /* end of records detected */
  735.         if(charcnt < 5) {
  736.         fprintf(stderr,"%c", linebuf[0]); fflush(stderr);
  737.         continue;    /* must be AAA, BBB, ... */
  738.         }
  739.  
  740.         /* Clear all storage arrays. */
  741.         lastname[0] = firstini[0] = affiliation[0] = emaddress[0] = '\0';
  742.  
  743.         recordcnt++;    /* only count real address record */
  744.         /* We've got a reasonable line.  First, get the lastname */
  745.         findex(linebuf, ',');        /* check if a comma is present */
  746.         sscanf(linebuf, "%[^,]", lastname);    /* read to before comma */
  747.  
  748.         /* Get the firstname plus initial */
  749.         strncpy(tmpbuf, linebuf, 250);
  750.         bptr = findex(tmpbuf, ',');
  751.         while((c = *++bptr) == ' ' || c == '\t') ;    /* non-space after comma */
  752.         eptr = findex(tmpbuf, '(');
  753.         while((c = *--eptr) == ' ' || c == '\t') ;    /* non-space before '(' */
  754.         if(eptr >= bptr) {
  755.         eptr++; *eptr = '\0';        /* make sure there is firstname part */
  756.         strncpy(firstini, bptr, 60);
  757.         } else
  758.         strcpy(firstini, "");        /* no firstname/initial */
  759.  
  760.         /* Get institutional affilication enclosed in bracket */
  761.         strncpy(tmpbuf, linebuf, 250);
  762.         bptr = findex(tmpbuf, '(');
  763.         eptr = findex(tmpbuf, ')');
  764.         bptr++;        /* char after '(' */
  765.         *eptr = '\0';    /* terminate string at ')' */
  766.         strncpy(affiliation, bptr, 60);
  767.  
  768.         /* Get (1-st part of) E-mail address.  It should also work
  769.            even if the e-mail address is entirely on the continuation
  770.            line and there is nothing after the closing bracket.
  771.          */
  772.         eptr++;    /* eptr pointing to tmpbuf is still good */
  773.         sscanf(eptr, "%s", emaddress);    /* read email address to EOL */
  774.  
  775.         /* Check for continuation of email address.
  776.          * We just look for a space character in the first column.
  777.          */
  778.         if((c = getc(fpi)) != ' ')
  779.         ungetc(c, fpi);            /* not a continuation line */
  780.         else {
  781.         ungetc(c, fpi);            /* looks like a continuation line */
  782.         if((fgets(linebuf, 250, fpi)) == NULL) break;    /* get cont. line */
  783.         linecnt++;
  784.         bptr = findex(linebuf, '"');    /* check continuation marker <"> */
  785.         while((c = *++bptr) == ' ' || c == '\t') ;
  786.         sscanf(bptr, "%s", tmpbuf);    /* 2-nd part of address in tmpbuf */
  787.         strncat(emaddress, tmpbuf, 80); /* Join 2-nd part to 1-st part */
  788.         } /* end if((c= getc(fpi)..) else{} */
  789.  
  790.         /* Remove comma, if present, from Firstname-initial, and
  791.          * Institutional affiliation
  792.          */
  793.         remove_comma(firstini);
  794.         remove_comma(affiliation);
  795.  
  796.         /* Check if e-mail address contains any bad character. */
  797.         c = check_address(emaddress);
  798.         if(c) {
  799.         fprintf(stderr, "\nLine %d - Warning: strange character \"%c\" in e-mail address:\n",
  800.                 linecnt, c);
  801.         fprintf(stderr, "  %s, %s (%s) %s\n", lastname, firstini, affiliation, emaddress);
  802.         }
  803.  
  804.         /* OK, we must now have everything collected for a record.
  805.          * Output the record in the format desired.
  806.          */
  807.         write_record(fpo);
  808.  
  809.     } /* end while((fgets(linebuf, .... ) */
  810.  
  811.  
  812.     /* Read optional epilog from format file into output file */
  813.     if(strncmp(fLineBuffer, "$E", 2) == 0) {
  814.         quote = fLineBuffer[2];        /* set quote char for epilog */
  815.         bptr = &fLineBuffer[3];
  816.         while(1){
  817.             while(((c = *bptr++) != quote) && c != '\0')
  818.                 putc(c, fpo);
  819.             if(c == quote) break;
  820.             if(fgets(fLineBuffer, 250, fpf) == NULL) break;
  821.             bptr = fLineBuffer;
  822.         }
  823.             fLineBuffer[0]=0;
  824.             fgets(fLineBuffer, 250, fpf);    /* read next line */
  825.     } 
  826.  
  827.     fprintf(stderr, "\n%d records processed. Conversion done.\n", recordcnt);
  828.     fclose(fpf);
  829.     fclose(fpi);
  830.     fclose(fpo);
  831. #ifdef MAC
  832.         printf("Click this window to exit:\n");
  833.         FlushEvents(everyEvent,0);
  834.         while(!GetNextEvent(everyEvent,&event)) ;
  835. #endif
  836. }
  837.